//
//  CYAppLauncher.m
//  cyjf
//
//  Created by tauCross on 2017/4/17.
//  Copyright © 2017年 Auto Financing. All rights reserved.
//

#import "CYAppLauncher.h"

#import "CYAppCleaner.h"

#import "CYMainController.h"
#import "CYLoadingViewController.h"
#import "CYGuideViewController.h"
#import "CYUpgradeView.h"
#import "CYPopupAdView.h"
#import "CYSudokuVerifyViewController.h"
#import "CYLaunchAdViewController.h"

#import "CYActionManager.h"
#import "CYShareManager.h"
#import "CYSudokuManager.h"
#import "CYLaunchAdvertisementManager.h"
#import "CYPopupAdvertisementManager.h"
#import "CYLocationManager.h"

#import <IQKeyboardManager.h>
#import <JPUSHService.h>
#import <UserNotifications/UserNotifications.h>
#import <TCJSONKit.h>
#import <UMMobClick/MobClick.h>



@interface CYAppLauncher ()<JPUSHRegisterDelegate>

@property(nonatomic, strong)NSDictionary *launchOptions;
@property(nonatomic, strong)CYDataAPIActionModel *action;

@end


@implementation CYAppLauncher

+ (void)startWithOptions:(NSDictionary *)launchOptions
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [[CYAppLauncher standardLaunch] startWithOptions:launchOptions];
    });
}

+ (instancetype)standardLaunch
{
    [[CYDustManager standardManager] dustMsg];
    static CYAppLauncher *launcher = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        launcher = [[CYAppLauncher alloc] init];
        [[NSNotificationCenter defaultCenter] addObserver:launcher selector:@selector(onReceiveApplicationDidEnterBackgroundNotification) name:UIApplicationDidEnterBackgroundNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:launcher selector:@selector(onReceiveApplicationWillEnterForegroundNotification) name:UIApplicationWillEnterForegroundNotification object:nil];
    });
    return launcher;
}

- (void)startWithOptions:(NSDictionary *)launchOptions
{
    [[CYDustManager standardManager] dustMsg];
    [CYAppCleaner clear];
    self.launchOptions = launchOptions;
    NSDictionary *userInfo = self.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
    if([userInfo isKindOfClass:[NSDictionary class]])
    {
        if([userInfo[@"action"] isKindOfClass:[NSString class]])
        {
            self.action = [CYDataAPIActionModel mj_objectWithKeyValues:[userInfo[@"action"] tc_JSONObject]];
        }
    }
    [self launchPart];
    [self checkNetworking];
}

#pragma mark - Notifications
- (void)onReceiveApplicationDidEnterBackgroundNotification
{
    [CYSudokuManager setHoldDate];
}

- (void)onReceiveApplicationWillEnterForegroundNotification
{
    if([[UIApplication sharedApplication] delegate].window.rootViewController == [CYMainController standardController].navigationController)
    {
        [self checkSudokuFromBackground];
    }
}

#pragma mark - checker
- (void)checkNetworking
{
    [self launchWindow];
    @weakify(self);
    CYLoadingViewController *loadingViewController = [[CYLoadingViewController alloc] init];
    loadingViewController.complete = ^{
        @strongify(self);
        [self checkGuide];
        [self launchLocation];
    };
    [[[UIApplication sharedApplication] delegate] window].rootViewController = loadingViewController;
}

- (void)checkGuide
{
    [[CYDustManager standardManager] dustMsg];
    NSNumber *currentGuideVersion = [CYGuideViewController currentGuideVersion];
    NSArray *historyGuideVersion = [[NSUserDefaults standardUserDefaults] arrayForKey:@"cyjf_guide_versions"];
    historyGuideVersion = historyGuideVersion ? : [NSArray array];
    if(!([historyGuideVersion containsObject:currentGuideVersion]))
    {
        @weakify(self);
        CYGuideViewController *guideViewController = [[CYGuideViewController alloc] init];
        [[[UIApplication sharedApplication] delegate] window].rootViewController = guideViewController;
        guideViewController.complete = ^{
            @strongify(self);
            NSMutableArray *ha = [historyGuideVersion mutableCopy];
            [ha addObject:currentGuideVersion];
            [[NSUserDefaults standardUserDefaults] setObject:ha forKey:@"cyjf_guide_versions"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [self checkSudoku];
        };
    }
    else
    {
        [self checkLaunchAdvertisement];
    }
}

- (void)checkLaunchAdvertisement
{
    @weakify(self);
    [CYStandardLaunchAdvertisementManager fetchLocalObjectWithResult:^(CYLaunchAdvertisementObject *object) {
        @strongify(self);
        if(object)
        {
            CYLaunchAdViewController *launchAdViewController = [[CYLaunchAdViewController alloc] init];
            launchAdViewController.object = object;
            launchAdViewController.complete = ^(CYDataAPIActionModel *action) {
                @strongify(self);
                if(action)
                {
                    self.action = action;
                }
                [self checkSudoku];
            };
            [[UIApplication sharedApplication] delegate].window.rootViewController = launchAdViewController;
        }
        else
        {
            [self checkSudoku];
        }
    }];
}

- (void)checkSudoku
{
    if([CYSudokuManager needVerify])
    {
        @weakify(self);
        CYSudokuVerifyViewController *sudokuVerifyViewController = [[CYSudokuVerifyViewController alloc] init];
        sudokuVerifyViewController.complete = ^(BOOL success) {
            @strongify(self);
            if(!success)
            {
                [self launchUI];
                [self launchRemoteNotification];
                CYStandardAuthManager.currentAuth = nil;
                [CYStandardAuthManager saveAuth];
                [[CYMainController standardController] goHome];
                [[CYMainController standardController] showLogIn];
            }
            else
            {
                [self checkComplete];
            }
        };
        [[UIApplication sharedApplication] delegate].window.rootViewController = sudokuVerifyViewController;
    }
    else
    {
        [self checkComplete];
    }
}

- (void)checkComplete
{
    [self launchUI];
    [self checkUpgrade];
    [self launchRemoteNotification];
    [self checkAction];
}

- (void)checkSudokuFromBackground
{
    if([CYSudokuManager needVerify])
    {
        CYSudokuVerifyViewController *sudokuVerifyViewController = [[CYSudokuVerifyViewController alloc] init];
        sudokuVerifyViewController.complete = ^(BOOL success) {
            [[UIApplication sharedApplication] delegate].window.rootViewController = [CYMainController standardController].navigationController;
            if(!success)
            {
                CYStandardAuthManager.currentAuth = nil;
                [CYStandardAuthManager saveAuth];
                [[CYMainController standardController] goHome];
                [[CYMainController standardController] showLogIn];
            }
        };
        [[UIApplication sharedApplication] delegate].window.rootViewController = sudokuVerifyViewController;
    }
}

- (void)checkUpgrade
{
    [CYStandardDataAPI user_checkVersionWithComplete:^(CYResponse *response) {
        if(response.code == 0)
        {
            if([response.content isKindOfClass:[NSDictionary class]])
            {
                NSString *title = response.content[@"title"];
                NSNumber *type = response.content[@"type"];
                NSArray *texts = response.content[@"versionDesc2"];
                NSString *url = response.content[@"url"];
                if([title isKindOfClass:[NSString class]] &&
                   [type isKindOfClass:[NSNumber class]] &&
                   [texts isKindOfClass:[NSArray class]] &&
                   [url isKindOfClass:[NSString class]])
                {
                    BOOL flag = YES;
                    for(id string in texts)
                    {
                        if(![string isKindOfClass:[NSString class]])
                        {
                            flag = NO;
                        }
                    }
                    if(flag)
                    {
                        if(type.integerValue == 1 || type.integerValue == 2)
                        {
                            CYUpgradeViewType theType;
                            if(type.integerValue == 1)
                            {
                                theType = CYUpgradeViewTypeOption;
                            }
                            else
                            {
                                theType = CYUpgradeViewTypeRequire;
                            }
                            CYUpgradeView *view = [[CYUpgradeView alloc] initWithTitle:title type:theType texts:texts url:url];
                            [view show];
                            return;
                        }
                    }
                }
            }
        }
        [self checkPopupAd];
    }];
}

- (void)checkPopupAd
{
    if(self.action == nil)
    {
        [CYStandardPopupAdvertisementManager fetchLocalObjectWithResult:^(CYPopupAdvertisementObject *object) {
            if(object)
            {
                CYPopupAdView *view = [[CYPopupAdView alloc] initWithObject:object];
                [view show];
            }
        }];
    }
}

- (void)checkAction
{
    if(self.action)
    {
        [CYStandardActionManager executeActionWithModel:self.action fromViewController:[CYMainController standardController]];
    }
}

#pragma mark - Launcher
#pragma mark - RemoteNotification
- (void)launchRemoteNotification
{
    JPUSHRegisterEntity *entity = [[JPUSHRegisterEntity alloc] init];
    entity.types = JPAuthorizationOptionAlert | JPAuthorizationOptionBadge | JPAuthorizationOptionSound;
    [JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
    [JPUSHService setupWithOption:self.launchOptions appKey:JPUSH_KEY channel:nil apsForProduction:JPUSH_IS_PRODUCTION];
}

#pragma mark - UI
- (void)launchUI
{
    [self launchAppearance];
    [self launchRootViewContoller];
}

- (void)launchWindow
{
    UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    [window makeKeyAndVisible];
    [[[UIApplication sharedApplication] delegate] setWindow:window];
}

- (void)launchRootViewContoller
{
    [[[[UIApplication sharedApplication] delegate] window] setRootViewController:[CYMainController standardController].navigationController];
}

- (void)launchAppearance
{
    [[UITextField appearance] setTintColor:APP_DEFAULT_COLOR_RED];
    [[UIView appearance] setExclusiveTouch:YES];
}

#pragma mark - Part
- (void)launchPart
{
    [[CYDustManager standardManager] dustMsg];
    [self launchIQKeyboardManager];
    [self launchSVProgressHUB];
    [self launchUMeng];
    [self launchShareManager];
}

- (void)launchIQKeyboardManager
{
    [IQKeyboardManager sharedManager].enable = YES;
    [IQKeyboardManager sharedManager].enableAutoToolbar = NO;
}

- (void)launchSVProgressHUB
{
    [SVProgressHUD setMaximumDismissTimeInterval:2];
    [SVProgressHUD setDefaultMaskType:SVProgressHUDMaskTypeBlack];
}

- (void)launchUMeng
{
    [[CYDustManager standardManager] dustMsg];
    UMConfigInstance.appKey = UMENG_APP_KEY;
    UMConfigInstance.channelId = UMENG_APP_CHANNEL;
    [MobClick setAppVersion:CYAppVersion];
    [MobClick startWithConfigure:UMConfigInstance];
}

- (void)launchShareManager
{
    [CYShareManager standardManager];
}

- (void)launchLocation
{
    [CYLocationManager standardManager];
}

#pragma mark - JPUSHRegisterDelegate
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger options))completionHandler
{
    NSDictionary * userInfo = notification.request.content.userInfo;
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]])
    {
        [JPUSHService handleRemoteNotification:userInfo];
    }
    completionHandler(UNNotificationPresentationOptionAlert);
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wstrict-prototypes"
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler
#pragma clang diagnostic pop
{
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
        if([userInfo[@"action"] isKindOfClass:[NSString class]])
        {
            CYDataAPIActionModel *action = [CYDataAPIActionModel mj_objectWithKeyValues:[userInfo[@"action"] tc_JSONObject]];
            [CYStandardActionManager executeActionWithModel:action fromViewController:[CYMainController standardController]];
        }
    }
    completionHandler();
}

@end
